﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using IM.Interfaces.GUI;
using IM.GUI.ContactList;
using System.Threading;
using IM.Interfaces;
using IM.DataTypes;

namespace IM.GUI.Conversation
{
	public partial class ConversationWindow : Control, IConversation
	{
		public new event Interfaces.Protocols.ObjectHandler OnLoad;
		public event Interfaces.Protocols.ObjectHandler OnQuit;

		internal static event ControlEventHandler OnControlCreated;

		SynchronizationContext uiContext;

		public ConversationWindow()
		{
			InitializeComponent();


			uiContext = WindowsFormsSynchronizationContext.Current;

			this.HandleDestroyed += new EventHandler(ConversationWindow_FormClosing);
			this.txbInput.Focus();

			if (OnControlCreated != null)
				OnControlCreated(this, new ControlEventArgs(this));
		}

		void ConversationWindow_FormClosing(object sender, EventArgs e)
		{
			//e.Cancel = true;
			this.Visible = false;
		}

		/// <summary>
		/// start new chat,
		/// this method is thread safe
		/// </summary>
		/// <param name="user">user to chat with</param>
		public void Show(User user)
		{
			uiContext.Send(new SendOrPostCallback(delegate(object state)
			{

				this.Show();
				this.Visible = true;
				this.tabControl1.Visible = true;
				this.txbInput.Visible = true;

				if (String.IsNullOrEmpty(user.Username))
					return;

				TabPage tab = tabControl1.TabPages[user.Username];

				if (tab == null)
				{
					tabControl1.TabPages.Add(user.Username, user.Nickname);
					tab = tabControl1.TabPages[user.Username];
					tab.Tag = user;

					var browser = CreateConversationBrowser();
					tab.Controls.Add(browser as Control);
				}

				tabControl1.SelectedTab = tab;
				// discard the background image, since it's hidden anyway
				this.BackgroundImage = null;
			}
			), null);
		}

		private IConversationBrowser CreateConversationBrowser()
		{
			var registeredNodes = Mono.Addins.AddinManager.GetExtensionNodes("/IM/GUI/Widgets/ConversationBrowser",
                typeof(IM.GUI.Widgets.ExtensionNodes.ConversationExtensionNode));

            Logging.Logger.AddImportant("Conversation Browser activate ");
			Dictionary<string, Common.Interfaces.IControlFactory> browsers = new Dictionary<string, Common.Interfaces.IControlFactory>();
			
            foreach (IM.GUI.Widgets.ExtensionNodes.ConversationExtensionNode node in registeredNodes)
            {
                //var capability = node.GetCapability();
				browsers.Add(node.Name, node.GetConversationFactory());
            }
			
			IConversationBrowser browser = null; //new ConversationBrowser();	//ConversationBrowser is default
			// TODO create some decision criteria
			if (!Logging.Logger.RuntimeIsMono.Value)
			{
				// FIXME - choosing by the name isn't really good
				var factory = browsers.Single(b => b.Key == "DefaultWebBrowser").Value;
				browser = factory.Create() as IConversationBrowser;
			}
			else
			{
				var factory = browsers.Single(b => b.Key == "HtmlRenderer").Value;
				browser = factory.Create() as IConversationBrowser;
			}
			
			return browser;
		}

		private void txbInput_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Enter)
			{
				String text = txbInput.Text;
				if (String.IsNullOrEmpty(text))
					return;

				TabPage tab = tabControl1.SelectedTab;
				if (tab != null)
				{
					User user = (tab.Tag as User);

					(tab.Controls[0] as IConversationBrowser).AddOutgoingMessage(user.Protocol.UserID.Nickname, text, DateTime.Now.ToShortTimeString());

					user.Protocol.SendMessage(text, user);
					txbInput.Text = String.Empty; 
				}
			}
			//TODO else send typing notification
		}

		/// <summary>
		/// add message to the chat window,
		/// this method is thread safe
		/// </summary>
		/// <param name="from"></param>
		/// <param name="message"></param>
		public void AddIncomingMessage(User from, string message)
		{
			uiContext.Send(new SendOrPostCallback(delegate(object state)
			{
				if (tabControl1.TabPages.ContainsKey(from.Username))
				{
					TabPage tab = tabControl1.TabPages[from.Username];
					(tab.Controls[0] as IConversationBrowser).AddIncomingMessage(from.Nickname, message, DateTime.Now.ToShortTimeString());
				}

			}), null);
		}

	}
}
